package com.ly.demo.weixin;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.ly.demo.exception.LYException;
import com.ly.demo.service.impl.RedisService;
import com.ly.demo.weixin.config.WeixinProperties;
import com.ly.demo.weixin.feign.WeixinFeign;
import com.ly.demo.weixin.feign.WeixinNeedTokenFeign;
import com.ly.demo.weixin.ienum.WxCodeEnum;
import com.ly.demo.weixin.req.GetAccessTokenReq;
import com.ly.demo.weixin.req.GetUserPhoneNumberReq;
import com.ly.demo.weixin.req.Jscode2sessionReq;
import com.ly.demo.weixin.rsp.GetAccessTokenRsp;
import com.ly.demo.weixin.rsp.GetUserPhoneNumberRsp;
import com.ly.demo.weixin.rsp.Jscode2sessionRsp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * @author: nieguochen
 * @date: 2024/1/15 14:18
 */
@Component
@Slf4j
public class WeixinManager {
    @Resource
    private WeixinFeign weixinFeign;
    @Resource
    private WeixinNeedTokenFeign weixinNeedTokenFeign;
    @Resource
    private WeixinProperties weixinProperties;
    @Resource
    private RedisService redisService;

    /**
     * 小程序登录
     *
     * @param code
     * @return
     */
    public Jscode2sessionRsp jscode2session(String code) {
        Jscode2sessionReq request = Jscode2sessionReq.builder()
                .appid(weixinProperties.getAppid())
                .secret(weixinProperties.getSecret())
                .grant_type(Jscode2sessionReq.GRANT_TYPE_DEFAULT)
                .js_code(code)
                .build();

        log.info("weixin.jscode2session.request: {}", JSONUtil.toJsonStr(request));

        String response = weixinFeign.jscode2session(request);
        log.info("weixin.jscode2session.response: {}", JSONUtil.toJsonStr(response));
        if (StringUtils.isBlank(response)) {
            throw new LYException(WxCodeEnum.WEIXIN_LOGIN_ERROR.getDesc(), WxCodeEnum.WEIXIN_LOGIN_ERROR.getCode());
        }
        return JSONUtil.toBean(response, Jscode2sessionRsp.class);
    }

    /**
     * 获取接口调用凭据
     *
     * @return
     */
    public String getAccessToken() {
        String lockKey = "weixin:getAccessToken";
        GetAccessTokenReq request = GetAccessTokenReq.builder()
                .appid(weixinProperties.getAppid())
                .secret(weixinProperties.getSecret())
                .grant_type(GetAccessTokenReq.GRANT_TYPE_DEFAULT)
                .build();
        log.info("weixin.getAccessToken.request: {}", JSONUtil.toJsonStr(request));
                GetAccessTokenRsp response = weixinFeign.getAccessToken(request);
                log.info("weixin.getAccessToken.response: {}", JSONUtil.toJsonStr(response));
                if (Objects.isNull(response) || StringUtils.isBlank(response.getAccess_token())) {
                    throw new LYException(WxCodeEnum.WEIXIN_GET_ACCESS_TOKEN_ERROR.getDesc(), WxCodeEnum.WEIXIN_GET_ACCESS_TOKEN_ERROR.getCode());
                }
                redisService.setWXAccessToken(response.getAccess_token(), response.getExpires_in());
                return response.getAccess_token();
    }

    /**
     * 获取用户手机号
     *
     * @param code
     * @param openId
     * @return
     */
    public GetUserPhoneNumberRsp getUserPhoneNumber(String code, String openId) {
        GetUserPhoneNumberReq request = GetUserPhoneNumberReq.builder()
                .code(code)
                .openid(openId)
                .build();

        log.info("weixin.getUserPhoneNumber.request: {}", JSONUtil.toJsonStr(request));

        GetUserPhoneNumberRsp response = weixinNeedTokenFeign.getUserPhoneNumber(request);
        log.info("weixin.getUserPhoneNumber.response: {}", JSONUtil.toJsonStr(response));
        if (Objects.isNull(response) || Objects.isNull(response.getPhone_info()) || response.isFail()) {
            throw new LYException(WxCodeEnum.WEIXIN_GET_ACCESS_TOKEN_ERROR.getDesc(), WxCodeEnum.WEIXIN_GET_ACCESS_TOKEN_ERROR.getCode());
        }
        return response;
    }
}
